package com.authine.cloudpivot.util;

import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;

import java.awt.geom.Point2D;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Slf4j
public class PolygonUtil {


    /**
     * 数据格式样例：[[[[12576032.71781828,3283426.11797539],[12575869.74887867,3283382.35562195],[12575951.36968949,3283084.42322647],[12575956.12062139,3283067.55116773],[12575959.58797545,3283053.27628171],[12576126.93598884,3283100.54666212],[12576126.93598884,3283100.54666212],[12576126.93598884,3283100.54666212],[12576126.93598884,3283100.54666212],[12576122.04777951,3283127.20962209],[12576121.80769411,3283128.51917881],[12576118.90371999,3283144.35903766],[12576118.20023446,3283148.19623143],[12576118.20023446,3283148.19623143],[12576116.29279128,3283158.60046699],[12576100.66076036,3283243.86609015],[12576100.66076036,3283243.86609015],[12576042.39765408,3283405.9103545],[12576042.39765408,3283405.9103545],[12576032.71781828,3283426.11797539]]]]
     *
     * @param polyStr
     * @return
     * @throws Exception
     */
    public static List<Point2D.Double> parsePointDoubles(String polyStr){
        List<Point2D.Double> results = Lists.newArrayList();
        String str1 = polyStr.substring(2);
        String area = str1.substring(0, str1.length() - 2);
        List<ArrayList> arrayLists = JSONUtil.toList(area, ArrayList.class);
        for (ArrayList arrayList : arrayLists) {
            if (Objects.isNull(arrayList.get(0)) || Objects.isNull(arrayList.get(1))) {
                continue;
            }
            Double lngMc = ((BigDecimal) arrayList.get(0)).doubleValue();
            Double latMc = ((BigDecimal) arrayList.get(1)).doubleValue();
            Point2D.Double aDouble = new Point2D.Double(lngMc, latMc);
            results.add(aDouble);
        }
        return results;
    }


    /**
     * 判断点是否在多边形内
     *
     * @param point 测试点
     * @param pts   多边形的点
     * @return
     * @return boolean
     * @throws
     * @Title: IsPointInPoly
     * @Description: TODO()
     */
    public static boolean isInPolygon(Point2D.Double point, List<Point2D.Double> pts) {
        int N = pts.size();
        boolean boundOrVertex = true;
        int intersectCount = 0;//交叉点数量
        double precision = 2e-10; //浮点类型计算时候与0比较时候的容差
        Point2D.Double p1, p2;//临近顶点
        Point2D.Double p = point; //当前点

        p1 = pts.get(0);
        for (int i = 1; i <= N; ++i) {
            if (p.equals(p1)) {
                return boundOrVertex;
            }

            p2 = pts.get(i % N);
            if (p.x < Math.min(p1.x, p2.x) || p.x > Math.max(p1.x, p2.x)) {
                p1 = p2;
                continue;
            }

            //射线穿过算法
            if (p.x > Math.min(p1.x, p2.x) && p.x < Math.max(p1.x, p2.x)) {
                if (p.y <= Math.max(p1.y, p2.y)) {
                    if (p1.x == p2.x && p.y >= Math.min(p1.y, p2.y)) {
                        return boundOrVertex;
                    }

                    if (p1.y == p2.y) {
                        if (p1.y == p.y) {
                            return boundOrVertex;
                        } else {
                            ++intersectCount;
                        }
                    } else {
                        double xinters = (p.x - p1.x) * (p2.y - p1.y) / (p2.x - p1.x) + p1.y;
                        if (Math.abs(p.y - xinters) < precision) {
                            return boundOrVertex;
                        }

                        if (p.y < xinters) {
                            ++intersectCount;
                        }
                    }
                }
            } else {
                if (p.x == p2.x && p.y <= p2.y) {
                    Point2D.Double p3 = pts.get((i + 1) % N);
                    if (p.x >= Math.min(p1.x, p3.x) && p.x <= Math.max(p1.x, p3.x)) {
                        ++intersectCount;
                    } else {
                        intersectCount += 2;
                    }
                }
            }
            p1 = p2;
        }
        if (intersectCount % 2 == 0) {//偶数在多边形外
            return false;
        } else { //奇数在多边形内
            return true;
        }
    }

    public static void main(String[] args) throws Exception {
    }
}
